<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests\RevisionCreateRequest;
use App\Wiki;
use App\WikiRevision;
use App\Category;
use Auth;
use App\Services\WikiActivityLogService;
use Mews\Purifier\Facades\Purifier;
class WikiRevisionsController extends Controller
{
    protected $activityLog;
    public function __construct(WikiActivityLogService $activityLog)
    {
        $this->middleware('auth')->except('index', 'show');
        $this->activityLog = $activityLog;
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create(Wiki $wiki)
    {
        $categories = Category::with('children')->root()->get();
        return view('revisions.create', compact('categories', 'wiki'));
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(RevisionCreateRequest $request, Wiki $wiki, WikiRevision $revision)
    {
        $user = Auth::user();

        if ($wiki->frozen_at && !$user->hasAnyRole(['Founder', 'Administrator', 'Editor'])) {
            return redirect()->back()->with('warning', '该词条已被锁定，禁止编辑');
        }
        $revision->fill($request->all());
        // 检查是否做了修改
        $lastRevision = $wiki->version;
        if(!$this->checkChange($request, $lastRevision)) {
            return redirect()->back()->with('warning', '编辑失败！');
        }
        $revision->user_id = auth()->id();
        $revision->wiki_id = $wiki->id;
        $revision->save();
        $data = ['body' => $request->body];
        $revision->content()->updateOrCreate(['contentable_id' => $revision->id], $data);

        if ($requestCategory = $request->category) {
            // 处理分类
            $oldCategories = $lastRevision->categories->pluck('id')->toArray();
            $requestCategory = is_array($requestCategory) ?: explode(',', $requestCategory);

            $revision->categories()->sync($requestCategory);
            $revision->load('categories');
            // 更新
            foreach ($revision->categories as $category) {
                $category->refreshCache();
            }
            $this->activityLog->changeCategories($wiki, auth()->user(), $oldCategories, $requestCategory);
        }
        $this->activityLog->createdRevision($wiki, $revision);
        return redirect()->route('wiki.revisions.show', ['wiki' => $wiki->id, 'revision' => $revision->id])->with('成功创建一个版本');
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show(Wiki $wiki, WikiRevision $revision)
    {
        if($revision->wiki_id !== $wiki->id) {
            abort(404);
        }
        if ($revision->id === $wiki->version->id) {
            $revision->is_default_version = true;
        } else {
            $revision->is_default_version = false;
        }
        $comments = $wiki->comments()->paginate(10);
        $wiki_logs = $this->activityLog->getLogs($wiki);
        return view('wikis.show', compact('wiki', 'revision', 'comments', 'wiki_logs'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit(Wiki $wiki, WikiRevision $revision)
    {
        $user = Auth::user();
        $currentRevision = $wiki->getCurrentRevision();
        if (!$user->hasAnyRole(['Founder', 'Administrator', 'Editor'])) {
            if ($wiki->frozen_at) {
                return redirect()->back()->with('warning', '该词条已被锁定，禁止编辑');
            }
            // 只可以编辑最新版本

            if ($currentRevision->id !== $revision->id) {
                return redirect()->back()->with('warning', '这是一个历史版本，无法进行编辑');
            }
        }

        $categories = Category::with('children')->root()->get();

        return view('revisions.edit', compact('categories', 'wiki', 'revision'));
    }

    public function update(Request $request, Wiki $wiki, WikiRevision $revision)
    {
        $revision->fill($request->all());
        $revision->user_id = auth()->id();
        $revision->wiki_id = $wiki->id;
        $data = ['body' => $request->body];
        $revision->content()->updateOrCreate(['contentable_id' => $revision->id], $data);

        if ($requestCategory = $request->category) {
            // 处理分类
            // 记录旧 分类
            $oldCategories = $revision->categories->pluck('id')->toArray();
            $requestCategory = is_array($requestCategory) ?: explode(',', $requestCategory);

            $revision->categories()->sync($requestCategory);
            $revision->load('categories');
            // 更新
            foreach ($revision->categories as $category) {
                $category->refreshCache();
            }
            $this->activityLog->changeCategories($wiki, auth()->user(), $oldCategories, $requestCategory);
        }

        $revision->save();

        return redirect()->route('wiki.revisions.show', ['wiki' => $wiki->id, 'revision' => $revision->id])->with('成功修改一个版本');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }

    protected function checkChange($request, $version)
    {
        if(!$version) return true;
        $oldCategories = $version->categories->pluck('id')->toArray();
        $requestCategory = explode(',', $request->category);
        $newCategories = collect($requestCategory)->map(function ($i, $key) {
            return (int) $i;
        })->toArray();
        $contentChange = $version->content->body !== Purifier::clean($request->body);
        $categoryChange = $oldCategories !== $newCategories;

        if (!$contentChange && !$categoryChange) {
            return false;
        }
        return true;
    }
}
